/*
 * (c) Copyright 2014 Hewlett-Packard Development Company, L.P. All rights reserved.
 */
package com.hp.snap.gr.db.voltdb;

import com.hp.snap.gr.exception.DatabaseException;
import org.apache.commons.lang.BooleanUtils;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Yang, Lin
 * @since 3.2
 */
public class JSONHttpVoltDBClientFactory {
    private static final Logger logger = LoggerFactory.getLogger(JSONHttpVoltDBClientFactory.class);
    private final Map<String, JSONHttpVoltDBClient> clients = new HashMap<String, JSONHttpVoltDBClient>();

    public JSONHttpVoltDBClientFactory(Collection<VoltDBClientConfig> configs) {
        for (VoltDBClientConfig config : configs) {
            clients.put(config.getUrl(), new JSONHttpVoltDBClient(config));
        }
    }

    public JSONObject invokeStoredProcedure(String procedure, List<Object> params, boolean isThrowable) throws DatabaseException {
        for (Map.Entry<String, JSONHttpVoltDBClient> entry : clients.entrySet()) {
            try {
                String url = entry.getKey();
                JSONHttpVoltDBClient client = entry.getValue();
                JSONObject response = client.invokeStoredProcedure(procedure, params, isThrowable);
                if (response == null && !isThrowable) {
                    continue;
                }

                if (logger.isTraceEnabled()) {
                    logger.trace("VoltDB response from {}: {}", url, response.toString());
                }

                int status = response.getInt("status");
                int appstatus = response.getInt("appstatus");
                if (!BooleanUtils.toBoolean(status)) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("status {}, statusstring: {}", status, response.getString("statusstring"));
                    }
                    continue;
                }
                if (!BooleanUtils.toBoolean(appstatus)) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("appstatus {}, appstatusstring: {}", appstatus,
                                response.getString("appstatusstring"));
                    }
                }
                return response;
            } catch (Exception e) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Decode JSON response failed!", e);
                }
                continue;
            }
        }
        if (isThrowable) {
            throw new DatabaseException("Call VoltDB stored procedure failed. Please check the URI or access credentials" +
                    "and make sure it is running.");
        } else {
            return null;
        }
    }

    public JSONObject invokeStoredProcedure(String procedure, List<Object> params) throws DatabaseException {
        return invokeStoredProcedure(procedure, params, true);
    }
}
